package martin.tpfinal.reconocer.resolver;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.List;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

import org.apache.log4j.Logger;

import martin.tpfinal.common.conection.RequestServer;
import martin.tpfinal.common.conection.ResponseServer;
import martin.tpfinal.common.data.Constantes;
import martin.tpfinal.common.data.MyAudioFormat;
import martin.tpfinal.reconocer.FilePath;
import martin.tpfinal.reconocer.ServerProperties;
import martin.tpfinal.reconocer.comunicacion.Server;
import martin.tpfinal.reconocer.procesar.GenerateInput;
import martin.tpfinal.reconocer.red.Red;
import martin.tpfinal.reconocer.red.joone.RedJoone;
import martin.tpfinal.reconocer.wavToCoef.WavToCoef;
import martin.tpfinal.reconocer.wavToCoef.htk.WavToCoefHtk;


/**
 * Resuelve el proceso del archivo, hacia su traduccion
 */
public class ActionResolver {

    private static final Logger  logger  = Logger.getLogger(Server.class);
    
	private static int index=0;

	
	public ResponseServer execute(RequestServer request) {

		logger.info("Se recibio un sonido");
		//////////////////Guardo el archivo en una carpeta temporal/////////////////////
        byte audioBytes[] = request.getAudioFile();
        ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes);
        MyAudioFormat myAudioFormat=new MyAudioFormat();
        int frameSizeInBytes = myAudioFormat.getFormat().getFrameSize();
        AudioInputStream audioFile=new AudioInputStream(bais, myAudioFormat.getFormat(), audioBytes.length / frameSizeInBytes);

        int indice= index++;
        
        String fileName=(new FilePath()).getPathToTempDirectoryFile()+"sonido"+ indice +".wav";
        
        File archWav=createFile(fileName);
        	
        //guardo el archivo que me llego por socket en el path indicado
        saveToFile(archWav,audioFile);
 
        
        ///////////////////////mando a procesar el archivo//////////////////////////////
    	//levanto el archivo y lo proceso para obteber los archivos que voy a ingresar en la red
		String outFileName= (new FilePath()).getPathToTempDirectoryFile()+"mfcc"+ indice +".txt";
		File archTxt=createFile(outFileName);

		//obtengo los coeficientes a partir del archivo wav
        WavToCoef wavToCoef= new WavToCoefHtk();
		wavToCoef.transform(archWav, archTxt);
        
		//obtengo el vector que corresponde al coeficiente que quiero utilizar como entrada a mi red
		GenerateInput generateInput=new GenerateInput();
		List<Float> inToNet = generateInput.getInputToNet(archTxt);
		
       
		///////////////////////analizo la palabra en la red////////////////////////////
		Red red=new RedJoone();
		
		logger.info("Por ingresar a la red.");      
		String trainedNet = ServerProperties.getProperties().getProperty(ServerProperties.TRAINED_NET_NAME);
		String trainedNnets= (new FilePath()).getPathToDirectoryFile()+trainedNet;
		File trainedNnet = new File(trainedNnets);
       
		double[] palabraValue=red.run(inToNet,trainedNnet);
		DecimalFormat df = new DecimalFormat("0.00");
        
        logger.info("Salido de la red con:  "+df.format(palabraValue[0])+" ; "+df.format(palabraValue[1])+" ; "+df.format(palabraValue[2])); 
		
		String resultado = Constantes.getStringOfDouble(palabraValue);    
               
		logger.info("Se proceso el sonido, el resultado obtenido fue: "+resultado);
        //////////////////////genero el response///////////////////////////////////////
        ResponseServer response;
        
        if (Constantes.exitoso(resultado))
        	response = new ResponseServer(resultado,ResponseServer.EXITOSO);
        else
        	response = new ResponseServer(resultado,ResponseServer.FALLIDO);
			
		return response;
       
	}

	

	/**
	 * Guarda el archivo en un directorio local 
	 * de donde luego leere para reconocer
	 */
	public void saveToFile(File file,AudioInputStream audioFile) {

    	// reset to the beginnning of the captured data
    	try {
    		audioFile.reset();
    	} catch (Exception e) { 
    		return;
    	}

    	try {
    		if (AudioSystem.write(audioFile, AudioFileFormat.Type.WAVE, file) == -1) {
    			throw new IOException("Problems writing to file");
    		}
    	} catch (Exception ex) {
    	}
    	
    }

	
	private File createFile(String name){
        File arch=new File(name);
        if (arch.exists()){
        	if (arch.delete())
        		arch = new File(name);
        }

        return arch;
	}
	
//	public void test(){
//
//        String fileName=(new FilePath()).getPathToTempDirectoryFile()+"sonido1.wav";
// //       File archWav=createFile(fileName);
//        File archWav = new File(fileName);
//        
// 		WavToCoef wavToCoef= new WavToCoefHtk();
//		String outFileName= (new FilePath()).getPathToTempDirectoryFile()+"mfcc1.txt";
//        
//		File archTxt=createFile(outFileName);
//        
//		wavToCoef.transform(archWav, archTxt);
//       
//		GenerateInput generateInput=new GenerateInput();
//		double[][] inToNet = generateInput.getInput(archTxt);
//		
//       
//       ///////////////////////analizo la palabra en la red////////////////////////////
//       Red red=new RedJoone();
//              
//       String trainedNnets= (new FilePath()).getPathToDirectoryFile()+"nnet";
//       File trainedNnet = new File(trainedNnets);
//       
//       double[] palabraValue=red.run(inToNet,trainedNnet);
//       
//       String resultado = Constantes.getStringOfDouble(palabraValue);
//       
//       System.out.println(resultado);
//
//	}
//
//	public static void main(String[] args) {
//		ActionResolver actionResolver=new ActionResolver();
//		actionResolver.test();
//	}
  
}
